﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Mbs.Threading;
using System.Net.Sockets;

namespace Mbs.Net.Tcp
{
    public class Connector:IConnector
    {

        public ConnectionState State { get; protected internal set; }
        protected internal Socket Socket { get; private set; }

        public IServiceSender Sender { get; set; }
        public IServiceReceiver Receiver { get; set; }

        protected virtual void Init(HostInfo info)
        {
            Socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
           if(State != ConnectionState.Closed)
               throw new Exception("Connector has Opened!");

            Socket.NoDelay = true;
            LingerOption lingerOption = new LingerOption(true, 2);
            Socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Linger, lingerOption);
            Socket.SendTimeout = info.SendTimeout;
            Socket.ReceiveTimeout = info.ReceiveTimeout;
        }


        public void Open(HostInfo info,Action successCallback, Action<Exception> failCallback)
        {
            try
            {
                Init(info);

                State = ConnectionState.Opening;
                Socket.BeginConnect(info.EndPoint, ar =>
                {
                    try
                    {
                        Socket.EndConnect(ar);
                        State = ConnectionState.Opened;
                       
                        Sender.Init(info, this, Socket);
                        Receiver.Init(info, this, Socket);

                        if (successCallback != null)
                            successCallback();
                    }
                    catch (SocketException ex)
                    {
                        if (failCallback != null)
                            failCallback(ex);
                    }
                    catch (Exception ex)
                    {
                        if (failCallback != null)
                            failCallback(ex);
                    }



                }, null);
            }
            catch (SocketException ex)
            {
               if (failCallback != null)
                            failCallback(ex);
            }
            catch (Exception ex)
            {
               if (failCallback != null)
                            failCallback(ex);
            }

        }

        public void Close()
        {
            State = ConnectionState.Closed;

            Socket.SafeClose();
        }
    }
}
